//
// Created by 李传智 on 2018/4/14.
//

#include <libavutil/samplefmt.h>
#include "IPlayer.h"
#include "IDemux.h"
#include "IDecode.h"
#include "IResample.h"
#include "IAudioPlay.h"
#include "IVideoView.h"
#include "Logger.h"

IPlayer *IPlayer::get(unsigned char index) {
    static IPlayer players[256];
    return &players[index];
}

bool IPlayer::setDataSource(const char *url) {

    close();

    mutex.lock();
    if (!demux || !demux->open(url)) {
        LOG_E("demux open %s failed", url);
        mutex.unlock();
        return false;
    }

    // 解封装后可能是直接能播放的数据，不需要解码或者重采样，所以可能失败
    if (!videoDecode || !videoDecode->open(demux->getVideoCodecParameters(), isHardDecode)) {
        LOG_E("video decoder open %s failed, isHardDecode = %d", url, isHardDecode);
    }

    if (!audioDecode || !audioDecode->open(demux->getAudioCodecParameters())) {
        LOG_E("audio decoder open %s failed", url);
    }

    // 采样率如果和声音源的采样率不同，可能会有杂音
    audioOutParameter = demux->getAudioCodecParameters();
    // 格式一定要指定，有可能设备播放不了声音源采样格式
    audioOutParameter.format = 1; // AV_SAMPLE_FMT_S16
    audioOutParameter.channels = 2; // 声道数

    if (!resample || !resample->open(demux->getAudioCodecParameters(), audioOutParameter)) {
        LOG_E("audio resample failed");
    }

    mutex.unlock();

    return true;
}

void IPlayer::close() {
    mutex.lock();
    // 1. 关闭线程

    // 同步线程线程
    VideoThread::stop();
    // 解封装线程
    if (demux) {
        demux->stop();
    }
    // 解码线程
    if (audioDecode) {
        audioDecode->stop();
    }
    if (audioPlay) {
        audioPlay->stop();
    }
    if (videoDecode) {
        videoDecode->stop();
    }
    if (recorder) {
        recorder->stop();
    }

    // 2. 清理缓冲队列
    if (audioDecode) {
        audioDecode->clear();
    }
    if (videoDecode) {
        videoDecode->clear();
    }
    if (audioPlay) {
        audioPlay->clear();
    }

    // 3. 清理资源
    if (audioPlay) {
        audioPlay->close();
    }
    if (videoView) {
        videoView->close();
    }
    if (audioDecode) {
        audioDecode->close();
    }
    if (videoDecode) {
        videoDecode->close();
    }
//    if (recorder) {
//        recorder->close();
//    }
    if (demux) {
        demux->close();
    }

    mutex.unlock();
}

double IPlayer::getCurrentPosition() {

    double position = 0;

    mutex.lock();

    if (!demux || !videoDecode) {
        mutex.unlock();
        return position;
    }

    position = videoDecode->pts / (double) demux->duration;

    mutex.unlock();

    return position;
}

bool IPlayer::seek(double position) {

    bool ret = false;

    setPause(true);

    mutex.lock();

    if (demux) {
        mutex.unlock();
        setPause(false);
        return ret;
    }

    // 清理缓冲队列
    if (videoDecode) {
        videoDecode->clear();
    }

    if (audioDecode) {
        audioDecode->clear();
    }

    if (audioPlay) {
        audioPlay->clear();
    }

//    if (recorder) {
//        recorder->clear();
//    }

    ret = demux->seek(position); // 跳转到关键帧

    if (!videoDecode) {
        mutex.unlock();
        setPause(false);
        return ret;
    }

    int64_t seekPts = (int64_t) (demux->duration * position);

    // 跳转到实际显示的帧
    while (!isExist) {
        VideoData pkt = demux->read();
        if (pkt.size <= 0) {
            break;
        }
        if (pkt.isAudio) {
            if (pkt.pts < seekPts) {
                pkt.free();
                continue;
            }
            // 写入缓冲队列
            demux->notify(pkt);
            continue;
        }
        // 解码需要显示的帧之前的数据
        videoDecode->sendPacket(pkt);
        pkt.free();
        VideoData frame = videoDecode->receiveFrame();
        if (frame.size <= 0) {
            continue;
        }
        if (frame.pts >= seekPts) {
            break;
        }
    }

    mutex.unlock();

    setPause(false);

    return ret;
}

bool IPlayer::start() {
    mutex.lock();

    if (audioPlay) {
        audioPlay->startPlay(audioOutParameter);
    }

    if (audioDecode) {
        audioDecode->start();
    }

    if (videoDecode) {
        videoDecode->start();
    }

    if (!demux || !demux->start()) {
        LOG_E("demux start failed");
        mutex.unlock();
        return false;
    }

    VideoThread::start();

    mutex.unlock();

    return true;
}

void IPlayer::setPause(bool isPause) {
    mutex.lock();
    VideoThread::setPause(isPause);
    if (demux) {
        demux->setPause(isPause);
    }
    if (videoDecode) {
        videoDecode->setPause(isPause);
    }
    if (audioDecode) {
        audioDecode->setPause(isPause);
    }
    if (audioPlay) {
        audioPlay->setPause(isPause);
    }
    mutex.unlock();
}

void IPlayer::setRender(void *window) {
    if (videoView) {
        videoView->close();
        videoView->setRender(window);
    }
}

bool IPlayer::startRecord(const char *url) {
    mutex.lock();
    if (!demux) {
        mutex.unlock();
        return false;
    }
    if (recorder) {
        if (!recorder->open(url, audioOutParameter, demux->getVideoCodecParameters()) ||
            !recorder->start()) {
            mutex.unlock();
            LOG_E("IPlayer startRecord failed");
            return false;
        }
    }
    mutex.unlock();
    return true;
}

bool IPlayer::stopRecord() {
    mutex.lock();
//    if (recorder) {
//        recorder->stop();
//        recorder->close();
//    }
    mutex.unlock();
}

void IPlayer::main() {
    while (!isExist) {
        mutex.lock();

        if (!audioPlay || !videoDecode) {
            mutex.unlock();
            sleep(2);
            continue;
        }

        // 获取音频的pts,告诉视频
        videoDecode->syncPts = audioPlay->pts;

        mutex.unlock();
        sleep(2);
    }
}

